package com.asambleacristiana.repository.dao;

import java.lang.reflect.ParameterizedType;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;

public class AbstractDAO<T> implements GenericDAO<T> {

	private Class<T> persistentClass;
	private EntityManagerFactory entityManagerFactory;

	@SuppressWarnings("unchecked")
	public AbstractDAO(EntityManagerFactory entityManagerFactory) {
		this.entityManagerFactory = entityManagerFactory;
		this.persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
	}

	@Override
	public T findById(Object id) {
		EntityManager entityManager = entityManagerFactory.createEntityManager();
		try {
			return entityManager.find(persistentClass, id);
		} finally {
			entityManager.close();
		}

	}

	@SuppressWarnings("unchecked")
	@Override
	public List<T> findAll() {
		EntityManager entityManager = entityManagerFactory.createEntityManager();
		try {
			return entityManager.createQuery("from " + persistentClass.getSimpleName()).getResultList();
		} finally {
			entityManager.close();
		}
	}

	@Override
	public void persist(T entity) {
		EntityManager entityManager = entityManagerFactory.createEntityManager();
		EntityTransaction et = entityManager.getTransaction();
		et.begin();
		try {
			entityManager.merge(entity);
			et.commit();
		} catch (Exception e) {
			if (et.isActive()) {
				et.rollback();
			}
		} finally {
			if (entityManager != null) {
				entityManager.close();
			}
		}
	}

	@Override
	public void remove(T entity) {
		EntityManager entityManager = entityManagerFactory.createEntityManager();
		EntityTransaction et = entityManager.getTransaction();
		et.begin();
		try {
			entityManager.remove(entity);
			et.commit();
		} catch (Exception e) {
			if (et.isActive()) {
				et.rollback();
			}
		} finally {
			if (entityManager != null) {
				entityManager.close();
			}
		}

	}

	@Override
	public boolean update(T entity) {
		EntityManager entityManager = entityManagerFactory.createEntityManager();
		EntityTransaction et = entityManager.getTransaction();
		et.begin();
		try {
			entityManager.merge(entity);
			et.commit();
			return true;
		} catch (Exception e) {
			if (et.isActive()) {
				et.rollback();
			}
			return false;
		} finally {
			if (entityManager != null) {
				entityManager.close();
			}
		}

	}

}
